grammar Mql;

query : select ';';

select : 'SELECT' fieldList from where orderbyList? limit?;

where : 'WHERE' cond;

from : 'FROM' ID ('.' ID)?;

cond : cond 'AND' (cond 'AND')* cond  # andCond
     | cond 'OR' (cond 'OR')* cond   # orCond
     | '(' cond ')'                  # parCond
     | fieldExpr 'CONTAINS' wordExpr ('VALUE' FLOAT)? # containsCond
     | 'NOT' cond                    # notCond
     ;

wordExpr : 'NOT' wordExpr   # notWordExpr
         | wordExpr 'AND' wordExpr ('AND' wordExpr)* # andWordExpr
         | wordExpr 'OR' wordExpr ('OR' wordExpr)*   # orWordExpr
         | '(' wordExpr ')' # parWordExpr
         | STRING                                    # atomWordExpr

         ;

fieldExpr: 'NOT' fieldExpr   #notFieldExpr
         | fieldExpr 'AND' fieldExpr ('AND' fieldExpr)* # andFieldExpr
         | fieldExpr 'OR' fieldExpr ('OR' fieldExpr)*   # orFieldExpr
         | '(' fieldExpr ')' #parFieldExpr
         | ID                                           # idFieldExpr

         ;

orderby : ID ('ASC' | 'DESC')?;

orderbyList : 'ORDER BY' orderby (',' orderby)* ;

limit : 'LIMIT' INT (',' INT)?;

fieldList : ID (',' ID)* | '*';

LETTER : 'a'..'z' | 'A'..'Z';

ID : LETTER (LETTER | '0'..'9' | '_')* | 'this';

STRING : '"' (~[\r\n"] | '""')* '"';

CHAR :	'\'' . '\'' ;

INT :   '0'..'9'+ ;

FLOAT
	:	INT '.' INT*
	|	'.' INT+
	;

WS  :   (' '|'\r'|'\t'|'\n') -> channel(HIDDEN)
    ;

SL_COMMENT : '#' ~('\r' | '\n')* '\r'? '\n' -> channel(HIDDEN);